
// 深拷贝 ES5
function deepCopy(object) {
  // 只拷贝对象
  if (!object || typeof object !== 'object') return object;
  // 根据 object 的类型判断是新建一个数组还是对象
  let newObject = Array.isArray(object) ? []: {}
  // 遍历 object，并且判断是 object 的属性才拷贝
  for(let k in object) {
    if (object.hasOwnProperty(k)) {
      newObject[k] =
        typeof object[k] === 'object'? deepCopy(object[k]): object[k];
    }
  }
  return newObject;
}


function deepCloneES5(origin, target) {
  let tar = target || {},
      // toStr = Object.prototype.toString,
      toStr = Reflect.toString,
      arrType = '[object Array]';
  
  for (let k in origin) {
    if (origin.hasOwnProperty(k)) {
      if (typeof origin[k] === 'object' && origin[k] !== null) {
        tar[k] = toStr.call(origin[k]) === arrType ? []: {};
        deepCloneES5(origin[k], tar[k]);
      } else {
        tar[k] = origin[k];
      }
    }
  }
  return tar;
}




// 深拷贝 ES6

// WeakMap() 防止内存泄漏
// 只接受对象作为key（键名），所引用的对象都是弱引用
// 只要对象的其他引用被删除，垃圾回收机制就会释放该对象占用的内存，从而避免内存泄漏
function deepClone(origin, hashMap = new WeakMap()) {
  if (origin == undefined || typeof origin !== 'object') return origin;

  if (origin instanceof Date) return new Date(origin);

  if (origin instanceof RegExp) return new RegExp(origin);
  
  // 获取WeakMap的键 并判断是否存在  // 作用：避免重复拷贝
  const hashKey = hashMap.get(origin);

  if (hashKey) return hashKey;

  // 使用构造器来判断是否是 {}、[]
  const target = new origin.constructor()

  // 保存一下键
  hashMap.set(origin, target)

  for (let k in origin) {
    if (origin.hasOwnProperty(k)) {
      target[k] = deepClone(origin[k], hashMap)
    }
  }

  return target;
}



// const obj = {}
// const newObj = new obj.constructor()
// newObj.a = 1
// console.log(obj)
// console.log(newObj)

// const arr = []
// const newArr = new arr.constructor()
// newArr.push(1)
// console.log(arr)
// console.log(newArr)

let test1 = {}
let test2 = {}

test2.test1 = test1
test1.test2 = test2

console.log(deepClone(test2))